Skip to content

chore(ci): API インベントリ差分検知の追加(API追加・認可回帰の機械検知) - #1894

Closed
mhaya wants to merge 4 commits into
mainfrom
chore/api-inventory-drift
Closed

chore(ci): API インベントリ差分検知の追加(API追加・認可回帰の機械検知)#1894
mhaya wants to merge 4 commits into
mainfrom
chore/api-inventory-drift

Conversation

@mhaya

@mhaya mhaya commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

概要 (Summary)

WEKO3 の全 HTTP エンドポイントを対象に、API の追加・仕様変更・認可の回帰を PR ごとに機械検知する仕組みを追加します。ツールとワークフローのみで、アプリケーションコードへの変更はありません。

  • tools/api-inventory/scripts/ — 生成・検証ツール一式
  • tools/api-inventory/ci/ — 設置手順(README.md)とワークフロー
  • .github/workflows/api-inventory-drift.yml
  • .github/pull_request_template.md — CI の想定に合わせて更新

変更タイプ (Type of Change)

  • 🚀 新機能追加 (Feature) — CI/開発基盤
  • 📚 仕様書・マニュアル・APIリストの更新 (Documentation)

このリポジトリにデータを置いていません

台帳(API 一覧とその調査結果)は、経路ごとの認可状況を含むため public な本リポジトリには置きません。別管理とし、ツールは環境変数 WEKO_API_INVENTORY_DIR で参照します。未設定なら理由を添えて中断します(scripts/paths.py)。

CI の出力も --summary-only件数のみです。Actions のログ・artifact・PR コメントは誰でも読めるため、URI や endpoint 名は出しません。出力に明細が混じっていないことを assert するステップも入れています。

Secret(API_INVENTORY_REPO / API_INVENTORY_SSH_KEY)が未設定の場合、ワークフローは何もせずスキップします。fork からの PR でも起動しません。

何を検知するか

内容
経路の増減 実機 url_map のスナップショット差分(追加/削除/URL変更/メソッド増減)
認可の変化 デコレータ集合の変化、認可のコメントアウト、permission factory の無効化
台帳との整合 実機にあって台帳に無い経路(抽出漏れ)の検出
到達可否 変更が触れた行に限定した実測(未認証で到達する書き込み系の検出)

経路の抽出は実機 url_map を正とします。 ソースの @blueprint.route / add_url_rule を AST で全部拾っても 357 ルートで、実機 903 ルート(static 除く)の 52% は Flask-Admin の自動生成・@expose・config 駆動 REST・modules/ 配下に無い pip パッケージ由来で、静的解析では原理的に見えないためです。

動作検証 (Verification)

実際に CI を走らせて全ステップ成功を確認しました。

run 32684278627  completed/success
  Check secrets / Checkout inventory data (private) / Start WEKO containers /
  Wait for web container / Run drift checks / Probe changed endpoints /
  Upload summary (counts only) / Teardown        すべて success

まっさらな CI 環境(install.sh --no-cache)でも、手元の環境と同一の結果になりました。

CI  : rules=972 modelviews=30  endpoints=860 (AST結合=495 / 属性不明=365)
手元: rules=972 modelviews=30  endpoints=860 (AST結合=495 / 属性不明=365)
台帳との突き合わせ: 差分 0

artifact が件数のみであることも確認済みです。

既知の制限

  • 到達可否の測定は modules/ 配下を変更した PR でのみ対象行が発生します。本 PR はツールのみのため対象 0 件で、実測経路は CI 上では未検証です(手元では検証済み)。
  • 測定用のテストデータは合成レコードのため、詳細画面のレンダリングを要する行やワークフローの activity を要する行は「判定不能」として明示的に除外されます。
  • ベースラインは CI と同じ環境(install.sh)で作る必要があります。異なる環境で作ると依存パッケージの版差で WARN が出続けます(ci/README.md §3b)。

既存 CI への影響

なし。既存の ui-tests.yml / unit-tests.yml には手を入れていません。追加するジョブは pull_requestworkflow_dispatch でのみ起動します。

導入手順

tools/api-inventory/ci/README.md に記載しています(配置、導入順序、ベースラインの更新ルール、ゲートが FAIL したときの対処、トラブルシュート)。

mhaya and others added 4 commits August 24, 2026 02:42
WEKO3 の全HTTPエンドポイントを棚卸しした台帳に対して、API の追加・仕様変更・
認可の回帰を PR ごとに機械検知する仕組み。

【このリポジトリは public のため、データは一切置かない】
台帳(weko3_api_list_full.tsv)は「どの経路を・どう叩けば・何が取れるか」と
実証結果を持つ。公開領域に置かず、秘密リポジトリで管理して環境変数
WEKO_API_INVENTORY_DIR で参照する(scripts/paths.py)。
CI の出力も --summary-only で件数のみ。Actions のログ・artifact・PRコメントは
誰でも読めるため、URI や endpoint 名は出さない。

- tools/api-inventory/scripts/  ツール一式
    Phase 1-3 静的抽出/観点付与/実機実測(既存の参考実装)
    Phase 5   build_checklist.py  57列 → 24列
    Phase 6   snapshot.py       実機url_map(UI/API両アプリ)+ModelView権限+AST属性
              diff_snapshot.py  スナップショット間の差分、ゲート G1-G7
              reconcile.py      スナップショット ↔ 台帳の突き合わせ(抽出漏れ検知)
              changed_rows.py   git差分 → 再レビューが必要な台帳行
    Phase 7   fixtures.py       到達可否測定用の最小コーパス投入
              probe_ci.py       フィクスチャ駆動の実測、ゲート G8/G9
    paths.py  $WEKO_API_INVENTORY_DIR の解決(未設定なら理由を添えて中断)

- tools/api-inventory/ci/  設置手順(README.md)とワークフロー
- .github/workflows/api-inventory-drift.yml
    Secret(API_INVENTORY_REPO / API_INVENTORY_TOKEN)が未設定なら何もせずスキップ。
    fork からの PR では起動しない。

- .github/pull_request_template.md  CI の想定に合わせて更新
    API変更PRでの秘密側ベースライン更新を必須項目化、ゲート対処表、
    公開領域にデータをコミットしていないことの確認項目

経路の抽出は実機 url_map を正とする。AST の @bp.route/add_url_rule では
357ルートしか拾えず、実機903ルート(static除く)の52%が Flask-Admin 自動生成・
@expose・config駆動REST・pip側パッケージ由来で原理的に見えないため。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HXo9u6PoTf6VRKr3aiGvZ3
Secret 判定 → deploy key での private checkout → 保存済みスナップショットと
台帳の突き合わせ、までを Docker なしで検証する。install.sh を回さないため
1分程度で終わる。--summary-only の出力に明細が混じっていないことも確認する。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HXo9u6PoTf6VRKr3aiGvZ3
配線確認は完了したので一時ワークフローを削除し、本番の api-inventory-drift を
push でも起動できるようにして実機込みで確認する。確認後に push トリガは削除する。

- push イベントでは pull_request.base.sha が無いため github.event.before に
  フォールバックする(changed_rows.py の比較元)
- job の if 条件を push イベントでも成立するようにした

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HXo9u6PoTf6VRKr3aiGvZ3
CI で全ステップ成功を確認したので後片付けと調整を行う。

- 一時的な push トリガを削除(トリガは pull_request / workflow_dispatch のみ)
- --summary-only でも W6(依存パッケージの版変化)はパッケージ名を出すようにした。
  公開PyPIの版情報で機密性が無く、名前が無いと原因を追えないため。
  経路名・所見を出さない方針は他のゲートで維持する。
- ci/README.md に「ベースラインは CI と同じ環境で作る」を追記。
  手元のdocker環境(302パッケージ)で作ったベースラインを CI の
  install.sh --no-cache 環境(301パッケージ)と比べると W6 が2件出る。
  経路(endpoints=860/AST結合=495/属性不明=365)は完全一致しており差は依存の版のみ。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HXo9u6PoTf6VRKr3aiGvZ3
@mhaya mhaya closed this Aug 24, 2026
@github-actions

Copy link
Copy Markdown

API インベントリ差分(件数のみ)

明細は公開できないため件数のみ表示しています。該当箇所は秘密側の台帳・レポートで確認してください。

ベースラインとの差分

API インベントリ差分レポート

  • 旧: d2fdc0e3b v2.0.3 (profile=default) endpoints=860 (外部ライブラリ由来 291)
  • 新: 81655cc2e v2.0.3-5-g81655cc2e (profile=default) endpoints=860 (外部ライブラリ由来 291)

判定: ✅ PASS (FAIL 0 / WARN 1)

サマリ

分類 件数
ADDED 0
REMOVED 0
RULE_CHANGED 0
METHODS_CHANGED 0
AUTH_CHANGED 0
IMPL_CHANGED 0
ATTRS_UNKNOWN_NEW 0
ModelView 追加 0
ModelView 削除 0
ModelView フラグ変化 0
config 変化 0
コメントアウト認証の増加 0
依存パッケージの版変化 2

[WARN] W6 依存パッケージの版が変化した — 2件

  • pyld — 3.1.0 -> 3.2.0
  • weko-redis — 0.1.0.dev20170000 -> (削除)

台帳との突き合わせ

スナップショット ↔ インベントリ 突き合わせ

  • リビジョン: 81655cc2e v2.0.3-5-g81655cc2e 経路URI=870
  • 台帳: 行=926 URI=881

件数のみ。詳細は秘密側の完全版レポートを参照。

判定: ✅ 一致 (0件)

検出 件数
A. インベントリ未収載(抽出漏れ) 0
B. 実機に無い(未説明) 0
B'. 実機に無い(既知・許容) 11
C. メソッド不一致 0
D. app列の不一致 0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant